/***************************************************************
*  Copyright (c) 2007 by GroupMe! Team (www.groupme.net)
*  All rights reserved.
*
*  This file is part of the GroupMe! Project. Source code of 
*  this project is closed and redistribution of this code is
*  prohibited. 
*  
*  Contact: http://www.groupme.net
*
*  This copyright notice MUST APPEAR in all copies of the file!
***************************************************************/
package net.groupme.controller.ajax;

import java.net.MalformedURLException;
import java.net.URL;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import net.groupme.controller.UserManagementController;
import net.groupme.controller.model.GroupBean;
import net.groupme.controller.model.HtmlFormattedElement;
import net.groupme.controller.model.UserForm;
import net.groupme.controller.model.UserFormMessages;
import net.groupme.exceptions.DeleteFailedException;
import net.groupme.exceptions.InsertFailedException;
import net.groupme.exceptions.UpdateFailedException;
import net.groupme.exceptions.UserNotExistingException;
import net.groupme.gui.constants.VIEW_VOCABULARY;
import net.groupme.gui.rendering.TagRenderer;
import net.groupme.model.Group;
import net.groupme.model.MODEL_CONSTANTS;
import net.groupme.model.ObjectFactory;
import net.groupme.model.User;
import net.groupme.model.dao.SQLDBController;
import net.groupme.search.GroupMeSearchEngine;
import net.groupme.search.SearchManager;
import net.groupme.search.strategy.model.WeightedTag;
import net.groupme.user.UserManager;
import net.groupme.user.UserManagerMessages;
import net.groupme.utils.sql.UserQueryUtility;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * created on Jun 21, 2007 
 * 
 * This GroupMe! ajax controller handles requests like <i>login</i> or <i>registration</i> of users.
 * The difference between this class and the {@link UserManagementController} is that
 * this class doesn't result in a new view but simply returns Java objects.
 * 
 * @author  Fabian Abel, <a href="mailto:abel@l3s.de">abel@l3s.de</a>
 * @author last edited by $Author: fabian $
 * 
 * @version $Revision: 1.27 $ $Date: 2009-04-22 18:28:55 $
 */
public class UserManagementAjaxController implements ApplicationContextAware{

	/** Logger for this class and subclasses */
	protected final Log logger = LogFactory.getLog(getClass());
	
	
	/** the application context */
	private ApplicationContext applicationContext = null;


	/**
	 * Creates an empty {@link UserManagementAjaxController} instance.
	 */
	public UserManagementAjaxController(){
		super();
	}
	
	/**
	 * Set the ApplicationContext that this object runs in. 
	 * @param applicationContext the current {@link ApplicationContext} 
	 */
	public void setApplicationContext(ApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
	}
	
	/**
	 * Login for users.
	 * @param username the username
	 * @param password the corresponding password
	 * @return <code>true</code> if login was successful, otherwise <code>false</code>
	 */
	public boolean login(String username, String password){
		UserManager manager = (UserManager) applicationContext.getBean(VIEW_VOCABULARY.USER_MANGER, UserManager.class);
		UserManagerMessages result = manager.login(username, password);
		if(UserManagerMessages.LOGIN_SUCCESSFUL.equals(result)){
			return true;
		}
		return false;
	}
	
	/**
	 * Logs out the actual user.
	 */
	public boolean logout(){
		UserManager manager = (UserManager) applicationContext.getBean(VIEW_VOCABULARY.USER_MANGER, UserManager.class);
		if (manager.getUser() == null){
			return false;
		}
		manager.logout();
		return true;
	}
	
	/**
	 * Returns the actual user as {@link UserForm} instance or an an empty {@link UserForm} instance...
	 * @return a {@link UserForm} instance with empty values.
	 */
	public UserForm getUserFormObject(){
		UserManager manager = (UserManager) applicationContext.getBean(VIEW_VOCABULARY.USER_MANGER, UserManager.class);
		if(manager.isLoggedIn()){
			return new UserForm(
					manager.getUser().getUserName(),
					"",
					manager.getUser().getFirstName(),
					manager.getUser().getLastName(),
					manager.getUser().getEmail(),
					manager.getUser().getFoaf(),
					manager.getUser().getPhoto()
					);
		}
		logger.info("It seems that the user is not logged in. Thus forms will be empty...");
		return new UserForm();
	}
	
	/**
	 * Returns an empty {@link UserFormMessages} bundle...
	 * @return a {@link UserFormMessages} instance with empty values.
	 */
	public UserFormMessages getUserFormMessagesObject(){
		return new UserFormMessages();
	}
	
	/**
	 * Registers a new User if all fields are valid.
	 * @param userForm the entered values as a {@link UserForm} instance
	 * @return a message bundle indicating which problems occur or idf everything was successful
	 */
	public UserFormMessages registerUser(UserForm userForm){
		UserFormMessages actualMessageBundle = new UserFormMessages();
		actualMessageBundle.setRegistrationSuccessFul(true);
		logger.info("Trying to register user: " + userForm);

		if(userForm == null){
			actualMessageBundle.setOverallMessage("Javascript is not enabled or session is no longer active. Please enable Javascript and/or reload the Website.");
			return actualMessageBundle;
		}

		//validate password entries:
		validatePassword(userForm, actualMessageBundle);
		
		//validate other user details:
		validatePersonalUserData(userForm, actualMessageBundle);
		
		//username:
		if(userForm.getUsername() == null || "".equals(userForm.getUsername())){
			actualMessageBundle.setUsernameMessage("Username should not be empty.");
			actualMessageBundle.setRegistrationSuccessFul(false);
		}
		
		//only if everything went ok so far, registration should be proceeded
		if(!actualMessageBundle.isRegistrationSuccessFul()){
			return actualMessageBundle;
		}
		
		//try to register the user to the data store..
		UserManager manager = (UserManager) applicationContext.getBean(VIEW_VOCABULARY.USER_MANGER, UserManager.class);
    	UserManagerMessages result = manager.register(userForm.getUsername(), userForm.getPassword(), userForm.getEmail(), userForm.getFirstName(), userForm.getLastName(), userForm.getFoafDocumentURL(), userForm.getPhoto());
    	
    	//DEBUG: register user
		//UserManagerMessages result = UserManagerMessages.REGISTRATION_SUCCESSFUL;
    	
    	if(UserManagerMessages.REGISTRATION_SUCCESSFUL.equals(result)){
    		actualMessageBundle.setOverallMessage("Registration successfull.");
    		actualMessageBundle.setRegistrationSuccessFul(true);
    	}else if(UserManagerMessages.USERNAME_ALLREADY_EXISTS.equals(result)){
    		actualMessageBundle.setUsernameMessage("Username already exists!");
    		actualMessageBundle.setRegistrationSuccessFul(false);
		}else if(UserManagerMessages.UPDATE_OR_INSERT_FAILED.equals(result)){
			actualMessageBundle.setOverallMessage("Problems during insert/update operation!!");
			actualMessageBundle.setRegistrationSuccessFul(false);
		} 	
		return actualMessageBundle;
	}
	
	
	/**
	 * Updates user details if all fields are valid.
	 * @param userForm the entered values as a {@link UserForm} instance
	 * @return a message bundle indicating which problems occur or idf everything was successful
	 */
	public UserFormMessages updateUserDetails(UserForm userForm){
		UserManager manager = (UserManager) applicationContext.getBean(VIEW_VOCABULARY.USER_MANGER, UserManager.class);
		if (manager.getUser() == null){
			return null;
		}
		UserFormMessages actualMessageBundle = new UserFormMessages();
		actualMessageBundle.setRegistrationSuccessFul(true);
		
		logger.info("Trying to update user: " + userForm);
		
		//validate user details:
		validatePersonalUserData(userForm, actualMessageBundle);
		
		logger.info("Actual validation status: " + actualMessageBundle.isRegistrationSuccessFul());
		
		//user details not valid:
		if(!actualMessageBundle.isRegistrationSuccessFul()){
			return actualMessageBundle;
		}
		//user details valid -> update user details:
		UserManagerMessages result = manager.updateDetails(userForm.getFirstName(), userForm.getLastName(), userForm.getEmail(), userForm.getFoafDocumentURL(), userForm.getPhoto());
		if(UserManagerMessages.UPDATE_SUCCESSFUL.equals(result)){
			actualMessageBundle.setOverallMessage("Update successfull.");
    		actualMessageBundle.setRegistrationSuccessFul(true);
		}else {
			actualMessageBundle.setOverallMessage("Problems occured on updating user details.");
    		actualMessageBundle.setRegistrationSuccessFul(false);
		}
		return actualMessageBundle;
	}
	
	/**
	 * Updates the user's password if all fields are valid.
	 * @param userForm the entered values as a {@link UserForm} instance
	 * @return a message bundle indicating which problems occur or idf everything was successful
	 */
	public UserFormMessages updatePassword(UserForm userForm){
		UserManager manager = (UserManager) applicationContext.getBean(VIEW_VOCABULARY.USER_MANGER, UserManager.class);
		if (manager.getUser() == null){
			return null;
		}
		UserFormMessages actualMessageBundle = new UserFormMessages();
		actualMessageBundle.setRegistrationSuccessFul(true);
		
		//validate password entries:
		validatePassword(userForm, actualMessageBundle);
		
		//user details not valid:
		if(!actualMessageBundle.isRegistrationSuccessFul()){
			return actualMessageBundle;
		}
		//user's password valid -> update user's password:
		UserManagerMessages result = manager.updatePassword(userForm.getPassword());
		if(UserManagerMessages.UPDATE_SUCCESSFUL.equals(result)){
			actualMessageBundle.setOverallMessage("Password changed successfully.");
    		actualMessageBundle.setRegistrationSuccessFul(true);
		}else {
			actualMessageBundle.setOverallMessage("Problems occured on changing password. Password was not changed");
    		actualMessageBundle.setRegistrationSuccessFul(false);
		}
		return actualMessageBundle;
	}
	
	
	/**
	 * Checks if password entries are valid and modifies the given {@link UserFormMessages} object
	 * if there are problems (like <i>re-typed password doesn't match the first entry</i>).
	 * @param userForm the actual user form entries
	 * @param actualMessageBundle the actual message bundle
	 */
	private void validatePassword(UserForm userForm, UserFormMessages actualMessageBundle){
		//password:
		if(userForm.getPassword() == null || "".equals(userForm.getPassword())){
			actualMessageBundle.setPasswordMessage("Password should not be empty.");
			actualMessageBundle.setRegistrationSuccessFul(false);
		}else if(!userForm.getPassword().equals(userForm.getPasswordb())){
			actualMessageBundle.setPasswordMessage("Password entries should be equal.");
			actualMessageBundle.setRegistrationSuccessFul(false);
		}
	}
	
	/**
	 * Checks if form entries about personal user stuff are valid and modifies the given {@link UserFormMessages} object
	 * if there are problems (like <i>no valid email address</i>).
	 * @param userForm the actual user form entries
	 * @param actualMessageBundle the actual message bundle
	 */
	private void validatePersonalUserData(UserForm userForm, UserFormMessages actualMessageBundle){
		//first name:
		if(userForm.getFirstName() == null || "".equals(userForm.getFirstName())){
			actualMessageBundle.setFirstNameMessage("First name should not be empty.");
			actualMessageBundle.setRegistrationSuccessFul(false);
		}
		else if(!userForm.getFirstName().matches("[0-9a-zA-Z_.@\\s-]+")){
			actualMessageBundle.setFirstNameMessage("First name may only contain letters, digits, whitespaces, underscores (_) , hyphen (-) ,at-signs (@) and dots (.).");
		}
		//last name:
		if(userForm.getLastName() == null || "".equals(userForm.getLastName())){
			actualMessageBundle.setLastNameMessage("Last name should not be empty.");
			actualMessageBundle.setRegistrationSuccessFul(false);
		}else if(!userForm.getLastName().matches("[0-9a-zA-Z_.@\\s-]+")){
			actualMessageBundle.setLastNameMessage("Last name may only contain letters, digits, whitespaces, underscores (_) , hyphen (-) ,at-signs (@) and dots (.).");
		}
		//email:
		if(userForm.getEmail() == null || "".equals(userForm.getEmail())){
			actualMessageBundle.setEmailMessage("Email should not be empty.");
			actualMessageBundle.setRegistrationSuccessFul(false);
		}else if(!userForm.getEmail().contains("@") || !userForm.getEmail().contains(".")){
			actualMessageBundle.setEmailMessage("No valid email address.");
			actualMessageBundle.setRegistrationSuccessFul(false);
		}
		
		//foaf (optinal)
		if(!"".equals(userForm.getFoafDocumentURL().trim())){
			try {
				new URL(userForm.getFoafDocumentURL());
			} catch (MalformedURLException e) {
				actualMessageBundle.setFoafDocumentURLMessage("No valid URL. Notice that the url of the foaf document is optional.");
				actualMessageBundle.setRegistrationSuccessFul(false);
			}
		}
		//photo (optinal)
		if(!"".equals(userForm.getPhoto().trim())){
			try {
				new URL(userForm.getPhoto());
			} catch (MalformedURLException e) {
				actualMessageBundle.setPhotoMessage("No valid URL. Notice that the url of the photo is optional.");
				actualMessageBundle.setRegistrationSuccessFul(false);
			}
		}
	}
	
	/**
	 * Removes a selected Group from the User Grouplist.
	 * @param group the group which should be deleted
	 * @return <code>true</code> if Group was deleted successfully, otherwise <code>false</code> 
	 */
	public boolean removeGroup(String groupID){
		UserManager manager = (UserManager) applicationContext.getBean(VIEW_VOCABULARY.USER_MANGER, UserManager.class);
		if (manager.getUser() == null){
			return false;
		}
		Group currentGroup = ObjectFactory.getGroup(groupID);
		if (manager.getUser().getURI().equals(currentGroup.getUsers("owner").iterator().next().getURI())){
			SQLDBController.removeGroupById(groupID);
			return true;
		}
		else{
			try {
				manager.getUser().removeGroup(currentGroup);
				return true;
			} catch (DeleteFailedException e) {
				logger.error("Error while deleting a Group from a Users Grouplist", e);
				return false;
			}
		}
	}
	
	/**
	 * Adds the given group to the users scubscribed groups.
	 * @param groupID the group which should be subscribed
	 * @return <code>true</code> if Group was subscribed successfully, otherwise <code>false</code>
	 */
	public boolean subscribeGroup(int groupID){
		UserManager manager = (UserManager) applicationContext.getBean(VIEW_VOCABULARY.USER_MANGER, UserManager.class);
		if (manager.getUser() == null){
			return false;
		}
		try {
			manager.subscribeGroup(groupID);
			return true;
		} catch (InsertFailedException e) {
			logger.error("Error while adding group with id " + groupID + " to users subscribed groups.");
			logger.error(e.getMessage());
			return false;
		}
	}
	
	
	/**
	 * Adds the given group to the users scubscribed groups.
	 * @param groupID the group which should be subscribed
	 * @return <code>true</code> if Group was subscribed successfully, otherwise <code>false</code>
	 */
	public boolean unsubscribeGroup(int groupID){
		UserManager manager = (UserManager) applicationContext.getBean(VIEW_VOCABULARY.USER_MANGER, UserManager.class);
		if (manager.getUser() == null){
			return false;
		}
		try {
			manager.unsubscribeGroup(groupID);
			return true;
		} catch (DeleteFailedException e) {
			logger.error("Error while removing group with id " + groupID + " from users subscribed groups.");
			logger.error(e.getMessage());
			return false;
		}
	}
	
	
	/**
	 * Returns all Groups of the current User as Beans in an Array.
	 * @return Array of GroupBean Objects
	 */
	public GroupBean[] getUsersGrouplist(){
		UserManager manager = (UserManager) applicationContext.getBean(VIEW_VOCABULARY.USER_MANGER, UserManager.class);
		Group[] groups = manager.getUser().getGroups().toArray(new Group[0]);
		GroupBean[] groupBeans = new GroupBean[groups.length];
		logger.info("Anzahl Gruppen:" + groups.length);
		for (int i = 0; i < groups.length; i++) {
			groupBeans[i] = new GroupBean(groups[i].getId(), groups[i].getName(), groups[i].getDescription());
		}
		return groupBeans;
	}
	
	/**
	 * Renames a given Group.
	 * @param groupID the ID of the Group to rename
	 * @param newName the new name for the group
	 */
	public boolean renameGroup(String groupID, String newName){
		UserManager manager = (UserManager) applicationContext.getBean(VIEW_VOCABULARY.USER_MANGER, UserManager.class);
		if (manager.getUser() == null){
			return false;
		}
		try {
			ObjectFactory.getGroup(groupID).setName(newName);
			return true;
		} catch (UpdateFailedException e) {
			logger.warn("Renaming of Group failed.", e);
			return false;
		}
	}
	
	/**
	 * Edits the Description of a given Group.
	 * @param groupID the ID of the Group to rename
	 * @param newDescription the new Description for the group
	 */
	public boolean editGroupDescription(String groupID, String newDescription){
		UserManager manager = (UserManager) applicationContext.getBean(VIEW_VOCABULARY.USER_MANGER, UserManager.class);
		if (manager.getUser() == null){
			return false;
		}
		try {
			ObjectFactory.getGroup(groupID).setDescription(newDescription);
			return true;
		} catch (UpdateFailedException e) {
			logger.warn("Editing of Group-Description failed.", e);
			return false;
		}
	}
	
	
	/**
	 * This method returns an ordered list of {@link WeightedTag} instances. Ordering is done according
	 * to the number of occurences in the given period. Such a list builds the base for <i>Tag Clouds</i>.
	 * This method simply calls {@link GroupMeSearchEngine#getTagCloud(Calendar, Calendar, User)}
	 * 
	 * @param startOfPeriod start of period (suggested format: yyyy-mm-dd). If this is <code>null</code> then all tag occurences that have 
	 * a date lesser than <i>endOfPeriod</i> are considered. 
	 * @param endOfPeriod end of period (suggested format: yyyy-mm-dd). If this is <code>null</code> then all tag occurences that have 
	 * a date greater than <i>beginOfPeriod</i> are considered. 

	 * @return an HTML-formatted tag cloud
	 */
	public HtmlFormattedElement getTagCloudForUser(String startOfPeriod, String endOfPeriod){
		logger.info("Visualizing tag cloud of user - start of period: " + startOfPeriod + " - end of period: " + endOfPeriod);
		User user = null;
		UserManager userManager = (UserManager) applicationContext.getBean(VIEW_VOCABULARY.USER_MANGER, UserManager.class);
		user = userManager.getUser();
		
		Calendar start = null;
		Calendar end = null;
		try{
			if(startOfPeriod != null && !"".equals(startOfPeriod)){
				DateFormat from = DateFormat.getDateInstance();
				from.parse(startOfPeriod);
				start = from.getCalendar();
			}
			if(endOfPeriod != null && !"".equals(endOfPeriod)){
				DateFormat	to = DateFormat.getDateInstance();
				to.parse(endOfPeriod);
				end = to.getCalendar();
			}
		}catch (Exception e){
			logger.error("Date format is wrong. Should be like:  yyyy-mm-dd", e);
		}
		SearchManager searchManager =(SearchManager) applicationContext.getBean(VIEW_VOCABULARY.GROUPME_SEARCH_MANGER, SearchManager.class);
		List<WeightedTag> weightedTags = searchManager.computeTagCloud(start, end, user, 10000000);//all tags...
		HtmlFormattedElement tagCloud = new HtmlFormattedElement(null, new TagRenderer().renderPersonalTagCloud(weightedTags));
		userManager.setCachedTagCloud(tagCloud);
		return tagCloud;
	}
	
	/**
	 * Constructs the tag cloud of the user, who corresponds to the given username.
	 * @param username the username of the user
	 * @return the tag cloud of the User
	 */
	public HtmlFormattedElement getTagCloudForUsername(String username){
		logger.info("Visualizing tag cloud of user " + username);
		User user = null;
		try {
			user = ObjectFactory.getUser(username);
		} catch (UserNotExistingException e) {
			e.printStackTrace();
			logger.error("Unable to get user " + username, e);
		}
		
		SearchManager searchManager =(SearchManager) applicationContext.getBean(VIEW_VOCABULARY.GROUPME_SEARCH_MANGER, SearchManager.class);
		List<WeightedTag> weightedTags = searchManager.computeTagCloud(null, null, user, 10000000);//all tags...
		HtmlFormattedElement tagCloud = new HtmlFormattedElement(null, new TagRenderer().renderPersonalTagCloud(weightedTags));
		return tagCloud;
	}
	
	/**
	 * Constructs the tag cloud with topK tags of the user, who corresponds to the given username.
	 * @param username the username of the user
	 * @return the tag cloud of the User
	 */
	public HtmlFormattedElement getTopKTagCloudForUsername(String username, int topK){
		logger.info("Visualizing top " + topK + " tag cloud of user " + username);
		User user = null;
		try {
			user = ObjectFactory.getUser(username);
		} catch (UserNotExistingException e) {
			e.printStackTrace();
			logger.error("Unable to get user " + username, e);
		}
		
		SearchManager searchManager =(SearchManager) applicationContext.getBean(VIEW_VOCABULARY.GROUPME_SEARCH_MANGER, SearchManager.class);
		List<WeightedTag> weightedTags = searchManager.computeTagCloud(null, null, user, topK);//topK tags...
		HtmlFormattedElement tagCloud = new HtmlFormattedElement(null, new TagRenderer().renderPersonalTagCloud(weightedTags));
		return tagCloud;
	}
	
	/**
	 * This method returns an ordered list of topK {@link WeightedTag} instances. Ordering is done according
	 * to the number of occurences in the given period. Such a list builds the base for <i>Tag Clouds</i>.
	 * This method simply calls {@link GroupMeSearchEngine#getTagCloud(Calendar, Calendar, User)}
	 *
	 * @param topK the topK tags to be returned
	 * @return an HTML-formatted tag cloud
	 */
	public HtmlFormattedElement getTopKTagCloudUser(String startOfPeriod, String endOfPeriod, int topK){
		User user = null;
		UserManager userManager = (UserManager) applicationContext.getBean(VIEW_VOCABULARY.USER_MANGER, UserManager.class);
		user = userManager.getUser();
		
		logger.info("Visualizing top " + topK + " tag cloud of user " + user.getUserName());
		
		Calendar start = null;
		Calendar end = null;
		try{
			if(startOfPeriod != null && !"".equals(startOfPeriod)){
				DateFormat from = DateFormat.getDateInstance();
				from.parse(startOfPeriod);
				start = from.getCalendar();
			}
			if(endOfPeriod != null && !"".equals(endOfPeriod)){
				DateFormat	to = DateFormat.getDateInstance();
				to.parse(endOfPeriod);
				end = to.getCalendar();
			}
		}catch (Exception e){
			logger.error("Date format is wrong. Should be like:  yyyy-mm-dd", e);
		}
		
		SearchManager searchManager =(SearchManager) applicationContext.getBean(VIEW_VOCABULARY.GROUPME_SEARCH_MANGER, SearchManager.class);
		List<WeightedTag> weightedTags = searchManager.computeTagCloud(start, end, user, topK);//topK tags...
		HtmlFormattedElement tagCloud = new HtmlFormattedElement(null, new TagRenderer().renderPersonalTagCloud(weightedTags));
		userManager.setCachedTagCloud(tagCloud);
		return tagCloud;
	}
	
	/**
	 * Constructs the tag cloud of the user, who corresponds to the given username.
	 * @param username the username of the user
	 * @return the tag cloud of the User
	 */
	public HtmlFormattedElement getNonPersonalTagCloudForUsername(String username){
		logger.info("Visualizing tag cloud of user " + username);
		User user = null;
		try {
			user = ObjectFactory.getUser(username);
		} catch (UserNotExistingException e) {
			e.printStackTrace();
			logger.error("Unable to get user " + username, e);
		}
		
		SearchManager searchManager =(SearchManager) applicationContext.getBean(VIEW_VOCABULARY.GROUPME_SEARCH_MANGER, SearchManager.class);
		List<WeightedTag> weightedTags = searchManager.computeTagCloud(null, null, user, 10000000);//all tags...
		HtmlFormattedElement tagCloud = new HtmlFormattedElement(null, new TagRenderer().renderTagCloud(weightedTags));
		return tagCloud;
	}
	
	/**
	 * Returns a list of user who match the given query pattern and who are not equal to the 
	 * user who is logged in at the moment.
	 * @param pattern pattern for username, firstname or lastname.
	 * @return a list of user who match the given query pattern
	 */
	public UserForm[] searchUsers(String pattern){
		List<User> users = UserQueryUtility.searchForUser(pattern);
		User loggedInUser =  ((UserManager) applicationContext.getBean(VIEW_VOCABULARY.USER_MANGER, UserManager.class)).getUser();
		
		ArrayList<UserForm> usersAsForms = new ArrayList<UserForm>();
		for(User user: users){
			if(loggedInUser == null || !user.getId().equals(loggedInUser.getId())){
				usersAsForms.add(new UserForm(user.getUserName(), null, user.getFirstName(), user.getLastName(), user.getEmail(), null, null));
			}
		}
		UserForm[] result = new UserForm[usersAsForms.size()];
		return usersAsForms.toArray(result);
	}
	
	/**
	 * Adds the given user as contributor to the given group if the user, who is logged in at the moment is
	 * really the owner of the group. It returns the current list of contributors or an empty array if something
	 * went wrong. 
	 * @param username the user to add as contributor 
	 * @param groupId the id of the group where the user should be a contributor
	 * @return the current list of contributors or an empty array if something
	 * went wrong. 
	 */
	public UserForm[] addContributor(String username, String groupId){
		logger.info("Add " + username + " as contributor to group " + groupId );
		User user =  ((UserManager) applicationContext.getBean(VIEW_VOCABULARY.USER_MANGER, UserManager.class)).getUser();
		Group group = ObjectFactory.getGroup(groupId);
		boolean reallyOwner = false;
		//check if the actual logged in user is really the owner
		if(user != null){
			for(User owner: group.getUsers(MODEL_CONSTANTS.ROLE_OWNER)){
				if(user.getId().equals(owner.getId())){
					reallyOwner = true;
				}
			}
		}
		User newContributor = null;
		try {
			newContributor = ObjectFactory.getUser(username);
		} catch (UserNotExistingException e) {
			e.printStackTrace();
			return new UserForm[0];
		}
		//is already a contributor?
		boolean isAlreadyContributor = false;
		for(User c: group.getUsers(MODEL_CONSTANTS.ROLE_EDITOR)){
			if(c.getId().equals(newContributor.getId())){
				isAlreadyContributor = true;
			}
		}
		if(isAlreadyContributor){
			ArrayList<UserForm> usersAsForms = new ArrayList<UserForm>();
			for(User c: group.getUsers(MODEL_CONSTANTS.ROLE_EDITOR)){
				usersAsForms.add(new UserForm(c.getUserName(), null, c.getFirstName(), c.getLastName(), c.getEmail(), null, null));
			}
			UserForm[] result = new UserForm[usersAsForms.size()];
			return usersAsForms.toArray(result);
		}else if(reallyOwner && newContributor != null  && !newContributor.getId().equals(user.getId())){
			try {
				group.addUser(MODEL_CONSTANTS.ROLE_EDITOR, newContributor);
			} catch (InsertFailedException e) {
				e.printStackTrace();
				return new UserForm[0];
			}
		}else{
			return new UserForm[0];
		}
		//get all actual contributors:
		ArrayList<UserForm> usersAsForms = new ArrayList<UserForm>();
		for(User c: group.getUsers(MODEL_CONSTANTS.ROLE_EDITOR)){
			usersAsForms.add(new UserForm(c.getUserName(), null, c.getFirstName(), c.getLastName(), c.getEmail(), null, null));
		}
		UserForm[] result = new UserForm[usersAsForms.size()];
		return usersAsForms.toArray(result);
	}
	
	
	/**
	 * Removes the given user as contributor to the given group if the user, who is logged in at the moment is
	 * really the owner of the group. 
	 * @param username the user to remove as contributor 
	 * @param groupId the id of the group where the user should no longer be a contributor
	 * @return the current list of contributors. 
	 */
	public UserForm[] removeContributor(String username, String groupId){
		logger.info("Remove " + username + " as contributor to group " + groupId );
		User user =  ((UserManager) applicationContext.getBean(VIEW_VOCABULARY.USER_MANGER, UserManager.class)).getUser();
		Group group = ObjectFactory.getGroup(groupId);
		boolean reallyOwner = false;
		//check if the actual logged in user is really the owner
		if(user != null){
			for(User owner: group.getUsers(MODEL_CONSTANTS.ROLE_OWNER)){
				if(user.getId().equals(owner.getId())){
					reallyOwner = true;
				}
			}
		}
		User contributorToRemove = null;
		try {
			contributorToRemove = ObjectFactory.getUser(username);
		} catch (UserNotExistingException e) {
			e.printStackTrace();
			return new UserForm[0];
		}
		//is really a contributor?
		boolean isReallyContributor = false;
		for(User c: group.getUsers(MODEL_CONSTANTS.ROLE_EDITOR)){
			if(c.getId().equals(contributorToRemove.getId())){
				isReallyContributor = true;
			}
		}
		if(reallyOwner && isReallyContributor && contributorToRemove != null && !contributorToRemove.getId().equals(user.getId())){
			try {
				group.removeUser(contributorToRemove);
			} catch (DeleteFailedException e) {
				e.printStackTrace();
			}
		}
		
		//get all actual contributors:
		ArrayList<UserForm> usersAsForms = new ArrayList<UserForm>();
		for(User c: group.getUsers(MODEL_CONSTANTS.ROLE_EDITOR)){
			usersAsForms.add(new UserForm(c.getUserName(), null, c.getFirstName(), c.getLastName(), c.getEmail(), null, null));
		}
		UserForm[] result = new UserForm[usersAsForms.size()];
		return usersAsForms.toArray(result);
	}
	
	
	/**
	 * Removes a selected Group from the User Grouplist.
	 * @param group the group which the user wants to leave as an editor.
	 * @return <code>true</code> if Group was left successfully, otherwise <code>false</code> 
	 */
	public boolean leaveGroup(String groupID){
		logger.info("Leave group " + groupID + " as contributor.");
		User user =  ((UserManager) applicationContext.getBean(VIEW_VOCABULARY.USER_MANGER, UserManager.class)).getUser();
		Group group = ObjectFactory.getGroup(groupID);
		boolean alsoOwner = false;
		//check if the actual logged in user is really the owner
		if(user != null){
			for(User owner: group.getUsers(MODEL_CONSTANTS.ROLE_OWNER)){
				if(user.getId().equals(owner.getId())){
					alsoOwner = true;
				}
			}
		}

		//is really a contributor?
		boolean isReallyContributor = false;
		for(User c: group.getUsers(MODEL_CONSTANTS.ROLE_EDITOR)){
			if(c.getId().equals(user.getId())){
				isReallyContributor = true;
			}
		}
		if(!alsoOwner && isReallyContributor && user != null){
			try {
				group.removeUser(user);
			} catch (DeleteFailedException e) {
				e.printStackTrace();
				return false;
			}
			return true;
		}
		return false;
	}
	
	
}
